|
nedoPC.orgElectronics hobbyists community established in 2002 |
|
Author |
Message |
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Впредь надо будет интерфейс шины Wishbone задействовать - проц Caravel может с пользовательским дизайном через эту шину общаться - можно на разные адреса вешать регистры и вообще память цеплять - вот тут подробности с примером: https://vlsi.jp/Introduction_to_OpenMPW.htmlПример на верилоге с тремя регистрами, доступными на запись и на чтение: | | | | Code: module wb_interface #( parameter TEST_CSR0 = 32'h3000_0000, parameter TEST_CSR1 = 32'h3000_0004, parameter TEST_CSR2 = 32'h3000_0008 )( // wishbone signals input wire wb_clk_i, input wire wb_rst_i, input wire wbs_stb_i, input wire wbs_cyc_i, input wire wbs_we_i, input wire [3:0] wbs_sel_i, input wire [31:0] wbs_dat_i, input wire [31:0] wbs_adr_i, output reg wbs_ack_o, output reg [31:0] wbs_dat_o, // CSRs output reg [31:0] test_csr0, output reg [31:0] test_csr1, output reg [31:0] test_csr2 );
localparam WB_IDLE = 2'b00; localparam WB_READ = 2'b01; localparam WB_WRITE = 2'b10;
reg [1:0] wb_state;
always @(posedge wb_clk_i) begin if(wb_rst_i) begin wb_state <= WB_IDLE; wbs_ack_o <= 1'b0; end else begin case(wb_state) WB_IDLE : begin wbs_ack_o <= 1'b0; if(wbs_stb_i && wbs_cyc_i) begin if(wbs_we_i) begin wb_state <= WB_WRITE; end else begin wb_state <= WB_READ; end end end WB_READ : begin wb_state <= WB_IDLE; wbs_ack_o <= 1'b1; case(wbs_adr_i) TEST_CSR0 : begin wbs_dat_o[7:0] <= wbs_sel_i[0] ? test_csr0[7:0] : 8'h00; wbs_dat_o[15:8] <= wbs_sel_i[1] ? test_csr0[15:0] : 8'h00; wbs_dat_o[23:16] <= wbs_sel_i[2] ? test_csr0[23:16] : 8'h00; wbs_dat_o[31:24] <= wbs_sel_i[3] ? test_csr0[31:24] : 8'h00; end TEST_CSR1 : begin wbs_dat_o[7:0] <= wbs_sel_i[0] ? test_csr1[7:0] : 8'h00; wbs_dat_o[15:8] <= wbs_sel_i[1] ? test_csr1[15:0] : 8'h00; wbs_dat_o[23:16] <= wbs_sel_i[2] ? test_csr1[23:16] : 8'h00; wbs_dat_o[31:24] <= wbs_sel_i[3] ? test_csr1[31:24] : 8'h00; end TEST_CSR2 : begin wbs_dat_o[7:0] <= wbs_sel_i[0] ? test_csr2[7:0] : 8'h00; wbs_dat_o[15:8] <= wbs_sel_i[1] ? test_csr2[15:0] : 8'h00; wbs_dat_o[23:16] <= wbs_sel_i[2] ? test_csr2[23:16] : 8'h00; wbs_dat_o[31:24] <= wbs_sel_i[3] ? test_csr2[31:24] : 8'h00; end default : begin wbs_dat_o <= 32'h0000_0000; end endcase end WB_WRITE : begin wb_state <= WB_IDLE; wbs_ack_o <= 1'b1; case(wbs_adr_i) TEST_CSR0 : begin test_csr0[7:0] <= wbs_sel_i[0] ? wbs_dat_i[7:0] : 8'h00; test_csr0[15:8] <= wbs_sel_i[1] ? wbs_dat_i[15:8] : 8'h00; test_csr0[23:16] <= wbs_sel_i[2] ? wbs_dat_i[23:16] : 8'h00; test_csr0[31:24] <= wbs_sel_i[3] ? wbs_dat_i[31:24] : 8'h00; end TEST_CSR1 : begin test_csr1[7:0] <= wbs_sel_i[0] ? wbs_dat_i[7:0] : 8'h00; test_csr1[15:8] <= wbs_sel_i[1] ? wbs_dat_i[15:8] : 8'h00; test_csr1[23:16] <= wbs_sel_i[2] ? wbs_dat_i[23:16] : 8'h00; test_csr1[31:24] <= wbs_sel_i[3] ? wbs_dat_i[31:24] : 8'h00; end TEST_CSR2 : begin test_csr2[7:0] <= wbs_sel_i[0] ? wbs_dat_i[7:0] : 8'h00; test_csr2[15:8] <= wbs_sel_i[1] ? wbs_dat_i[15:8] : 8'h00; test_csr2[23:16] <= wbs_sel_i[2] ? wbs_dat_i[23:16] : 8'h00; test_csr2[31:24] <= wbs_sel_i[3] ? wbs_dat_i[31:24] : 8'h00; end endcase end endcase end end
endmodule
| | | | |
|
30 Jun 2023 22:40 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Научился прошивать тестовую программку в девборду https://github.com/efabless/caravel_board/blob/main/gf180/blink/blink.cТеперь можно начинать писать свою программку для тестирования пользовательских внутренностей...
|
01 Jul 2023 00:06 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
На борту девборды установлен генератор 10 МГц - и похоже чип на такой частоте и работает т.к. вот такая функция: будучи вызвана с аргументом 5000000 выполняется ровно полсекунды
|
01 Jul 2023 00:24 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Чтобы USB-шнурок мог использоваться не только для прошивки, но и для последовательного взаимодействия нужно поставить вот этот джампер: После этого заработало на скорости 9600
|
01 Jul 2023 14:19 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Люди нашли способ настраивать входы-выходы так, чтобы можно было из проца подавать уровни на входы пользовательского модуля и читать выходы - теперь можно полноценно тестироваться
|
01 Jul 2023 23:43 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Написал программку для встроенного проца - всё работает как надо, включая C-гейт
|
02 Jul 2023 01:27 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Прошивальная питоновская утилитка у них периодически сбоила, поэтому я её им пофиксил и заслал пул-реквест https://github.com/efabless/caravel_board/pull/85P.S. Иногда оно всё же перехлёстывается - надо переписывать...
|
04 Jul 2023 01:02 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Под спойлером текст программки: blink_test.c | | | | Code: #include <defs.h> #include <stub.h> void println(){putchar('\n');} void print_bin(int byte) { int i; for(i=7;i>=0;i--) { if(byte&(1<<i)) putchar('1'); else putchar('0'); if(i==4) putchar(' '); } }
// -------------------------------------------------------- // Firmware routines // --------------------------------------------------------
void configure_io() {
// ======= Useful GPIO mode values =============
// GPIO_MODE_MGMT_STD_INPUT_NOPULL // GPIO_MODE_MGMT_STD_INPUT_PULLDOWN // GPIO_MODE_MGMT_STD_INPUT_PULLUP // GPIO_MODE_MGMT_STD_OUTPUT // GPIO_MODE_MGMT_STD_BIDIRECTIONAL // GPIO_MODE_MGMT_STD_ANALOG
// GPIO_MODE_USER_STD_INPUT_NOPULL // GPIO_MODE_USER_STD_INPUT_PULLDOWN // GPIO_MODE_USER_STD_INPUT_PULLUP // GPIO_MODE_USER_STD_OUTPUT // GPIO_MODE_USER_STD_BIDIRECTIONAL // GPIO_MODE_USER_STD_ANALOG
#define GPIO_MODE_MGMT_CONTROLLED_IO 0x00F #define GPIO_MODE_USER_CONTROLLED_IO 0x00E
// ======= set each IO to the desired configuration =============
// GPIO 0 is turned off to prevent toggling the debug pin; For debug, make this an output and // drive it externally to ground.
reg_mprj_io_0 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
// Changing configuration for IO[1-4] will interfere with programming flash. if you change them, // You may need to hold reset while powering up the board and initiating flash to keep the process // configuring these IO from their default values.
reg_mprj_io_1 = GPIO_MODE_MGMT_STD_OUTPUT; reg_mprj_io_2 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; reg_mprj_io_3 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; reg_mprj_io_4 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
// -------------------------------------------
reg_mprj_io_5 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; // UART Rx reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; // UART Tx reg_mprj_io_7 = GPIO_MODE_MGMT_STD_OUTPUT; // user inputs (tiny_silicon_1) reg_mprj_io_8 = GPIO_MODE_MGMT_CONTROLLED_IO; reg_mprj_io_9 = GPIO_MODE_MGMT_CONTROLLED_IO; reg_mprj_io_10 = GPIO_MODE_MGMT_CONTROLLED_IO; reg_mprj_io_11 = GPIO_MODE_MGMT_CONTROLLED_IO; reg_mprj_io_12 = GPIO_MODE_MGMT_CONTROLLED_IO; reg_mprj_io_13 = GPIO_MODE_MGMT_CONTROLLED_IO; reg_mprj_io_14 = GPIO_MODE_MGMT_CONTROLLED_IO; reg_mprj_io_15 = GPIO_MODE_MGMT_CONTROLLED_IO; // user outputs (tiny_silicon_1) reg_mprj_io_16 = GPIO_MODE_USER_CONTROLLED_IO; reg_mprj_io_17 = GPIO_MODE_USER_CONTROLLED_IO; reg_mprj_io_18 = GPIO_MODE_USER_CONTROLLED_IO; reg_mprj_io_19 = GPIO_MODE_USER_CONTROLLED_IO; reg_mprj_io_20 = GPIO_MODE_USER_CONTROLLED_IO; reg_mprj_io_21 = GPIO_MODE_USER_CONTROLLED_IO; reg_mprj_io_22 = GPIO_MODE_USER_CONTROLLED_IO; reg_mprj_io_23 = GPIO_MODE_USER_CONTROLLED_IO;
reg_mprj_io_24 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_25 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_26 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_27 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_28 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_29 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_30 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_31 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_32 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_33 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_34 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_35 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_36 = GPIO_MODE_USER_STD_OUTPUT; reg_mprj_io_37 = GPIO_MODE_USER_STD_OUTPUT;
#if 1 // Initiate the serial transfer to configure IO reg_mprj_xfer = 1; while (reg_mprj_xfer == 1); #endif }
void delay(const int d) {
/* Configure timer for a single-shot countdown */ reg_timer0_config = 0; reg_timer0_data = d; reg_timer0_config = 1;
// Loop, waiting for value to reach zero reg_timer0_update = 1; // latch current value while (reg_timer0_value > 0) { reg_timer0_update = 1; }
}
// inputs for tiny_silicon_1
#define CLK 0x01 #define DATA 0x02 #define CLK2 0x04 #define SET 0x08 #define RESET 0x10 #define NAND1 0x20 #define NAND2 0x40 #define DATA2 0x80
int testvec[] = { // testing D-trigger 0, CLK, 0, DATA, DATA|CLK, DATA, 0, CLK, 0, DATA, DATA|CLK, DATA, // testing D-trigger with SET/RESET 0, CLK2, 0, DATA, DATA|CLK2, DATA, 0, CLK2, 0, DATA, DATA|CLK2, DATA, DATA|RESET, DATA, 0, SET, 0, // testing RS-trigger built out of NAND-gates NAND1|NAND2, NAND1, NAND1|NAND2, NAND2, NAND1|NAND2, // testing C-gate NAND1|NAND2|DATA, NAND1|NAND2|DATA|DATA2, NAND1|NAND2|DATA, NAND1|NAND2, NAND1|NAND2|DATA, NAND1|NAND2|DATA|DATA2, NAND1|NAND2|DATA2, NAND1|NAND2, -1 };
void main() { int i, j, k;
reg_gpio_mode1 = 1; reg_gpio_mode0 = 0; reg_gpio_ien = 1; reg_gpio_oeb = 0;
configure_io();
reg_uart_enable = 1;
// Configure All LA probes as inputs to the cpu reg_la0_oenb = reg_la0_iena = 0x00000000; // [31:0] reg_la1_oenb = reg_la1_iena = 0x00000000; // [63:32] reg_la2_oenb = reg_la2_iena = 0x00000000; // [95:64] reg_la3_oenb = reg_la3_iena = 0x00000000; // [127:96]
// write data to la output // reg_la0_data = 0x00; // reg_la1_data = 0x00; // reg_la2_data = 0x00; // reg_la3_data = 0x00;
// read data from la input // data0 = reg_la0_data; // data1 = reg_la1_data; // data2 = reg_la2_data; // data3 = reg_la3_data;
print("Hello World !!\n");
i = j = 0; while (1) {
reg_gpio_out = 1; // OFF // reg_mprj_datah = 0x0000002a; // reg_mprj_datal = 0xaaaaaaaa; // reg_mprj_datal = i<<8; reg_mprj_datal = testvec[j++]<<8; if(testvec[j]<0) j = 0;
// delay(50000); delay(5000000);
reg_gpio_out = 0; // ON // reg_mprj_datah = 0x00000015; // reg_mprj_datal = 0x55555555; k = reg_mprj_datal;
// delay(50000); delay(5000000);
print("Counter: "); print_dec(i++); print(" : "); print_hex(k,8); print(" : "); print_bin(k>>8); print(" -> "); print_bin(k>>16); println(); }
}
| | | | |
и вот её вывод через USB (я только добавил туда расшифровку входов и выходов):
|
04 Jul 2023 21:07 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
В чипах Efabless сделанных по техпроцессу GF180 в качестве микроконтроллера встроена корка VexRiscv, что есть настраиваемая реализация RISC-V (см. https://github.com/SpinalHDL/VexRiscv). Она выполняет код прямо из последовательной SPI-флеши (на девборде стоит 4МБ флеш, способная работать на частотах до 133 МГц) и по слухам в корке есть какой-то маленький кэш инструкций (надо проверить). По памяти раскладка такая (вытащено из h-файла сгенерённого построителем корки, т.е. должно быть корректно): FLASH это адресное пространство программ, которое маппится на SPI-флеш (из 16-мегабайтного адресного пространства реально задействовано 4МБ); SRAM это реально присутствующее в чипе ОЗУ размером всего 2КБ - там располагается память данных; HK это область портов ввода-вывода, их настройки и чтения-записи; MPRJ это адресное пространство открываемое внутрь пользовательской логики по шине Wishbone (выше на этой странице есть пример реализации 3 регистров в этом адресном пространстве) - в моих чипах это адресное пространство не используется совсем. Проц работает на частоте 10 МГц, но есть возможность поставить джампер, который запретит осциллятор девборды и тогда клок надо будет пускать извне через ногу xclk (люди пробовали разгонять чип до 25 МГц). Последовательный порт на 9600 реализован через FTDI-чип и сразу идёт на USB гнездо (на линуксе оно обнаруживается как /dev/ttyUSB0 и работает через любую терминалку). Проверил некоторые адреса, а именно первая глобальная переменная, первая переменная в функции main, сама функция main и функция isr (обработчик прерываний): Получается, что isr тоже сидит в последовательной флеше, а локальные переменные, сидящие в стеке, пододвинуты ближе к концу памяти данных. P.S. Пытаюсь сравнить скорости исполнения из последовательного флеша и из памяти данных - можно создать глобальный массив 32-битных целых, скопировать туда какую-то функцию и запустить - в результате она будет работать существенно быстрее Например: Будучи запущенным из флеша код между сохранениями i1 и i2 (там примерно 12 инструкций) выполняется за 1104 такта, а из памяти данных - только 86 (что тоже многовато). Если поставить два global++ вместо одного (примерно 15 инструкций), то числа уже 1119 и 98 - получается один инкремент глобальной переменной в ОЗУ занимает 12 тактов, что есть 3 инструкции: Значит одна инструкция запускается тут за 4 такта! А вот если добавить третий global++ (примерно 18 инструкций), то числа уже станут 2192 и 130 соответственно (уже на 32 такта больше???). Если убрать global++ вовсе (тогда между замерами станет 9 инструкций), то цифры становятся 1095 и 53. Так что похоже кэш инструкций там таки есть и он перезаписывается примерно после 16 инструкций: P.P.S. Выровнял смещение для скопированной функции в памяти данных так, чтобы было как во флеше (первое сохранение текущего счётчика тактов приходится на начало 64-байтного блока) - теперь стало так (замеры только для ОЗУ): Ещё интересное наблюдение - 3 nop-a занимают меньше тактов (на 6 меньше), чем эти 3 инструкции: Хотя казалось бы, это RISC - всё должно быть одинаково (если это не передача управления), тем более NOP это на самом деле ADDI R0,R0,0 (хотя тут есть store инструкция - комнда sw, которая например в моей реализации была чуть дольше остальных)... P.P.P.S. Вот исходники версии Caravel-проца, что ставится в GF180: https://github.com/efabless/caravel_mgmt_soc_gf180mcu/tree/main
|
04 Jul 2023 21:36 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Вообще два раза подряд global++ без оптимизации компилируется вот так: т.е. сразу после сохранения переменной в памяти идёт чтение переменной из этой памяти, что может вызывать проблемы у RISC-процессоров - возможно корка ждёт, когда переменная будет записана прежде чем её прочитает, а может и не ждёт... По тактам значит получается так: Как можно видеть переход от 9 к 12 и потом к 15 инструкциям отличается на одинаковое кол-во тактов для флаша и для срама, а вот зашкал за 16 сильно длиннее у флеша т.к. там идёт заполнение кеша инструкций из SPI-флеша (а может глубина кеша 8, а не 16 и поэтому при 9 сразу много?). P.S. Потестил добавление NOP-ов по одному: Тут отчётливо видно, что кэш инструкций вмещает в себя 8 команд. P.P.S. Вот ещё замеры LW и SW:
|
05 Jul 2023 21:51 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Думаю сгенерить NTSC-сигнал программно на Caravel На 5 МГц 19 лет назад я так времянки раскладывал: Для 10 МГц можно поточнее цифры иметь: - NTSC строка имеет длину 63.5us, что превращается в 635 тактов; - видимая часть строки занимает 52.6us, что есть 526 тактов; - строчный синхроимпульс 4.7us это 47 тактов. Можно попробовать сделать так: 47-low 124-high 384-signal 80-high (полезный сигнал сужен, чтобы получить 32 клетки по 12 тактов каждая) Для точного позиционирования можно использовать timer0 в Periodic mode: https://caravel-mgmt-soc-litex.readthedocs.io/en/latest/generated/timer0.htmlКогда счёт идёт вниз от введённого значения и когда счётчик достигает 0, таймер снова взводится начальным значением и считает дальше - считать будем в пределах строки от 634 до нуля: - если новое число больше предыдущего (т.е. произошла перезагрузка счётчика), то устанавливаем синхру в 0; - если число стало меньше 587, то устанавливаем синхру в 1; - если число стало меньше 463, то начинаем вывод 384 пикселов (32 клетки по 12 тактов каждая); - далее ждём условия перезагрузки счётчика (см. пункт первый). Вывод 32 клеток кодом из ОЗУ: | | | | Code: asm volatile( "nop\n" "nop\n" "nop\n" "lw a4,8(zero)\n"// ...30 "lui a5,0x26000\n"// ...34 "addi a5,a5,12\n" // ...38 "li a2,32\n" // ...3C <<< N= 1, 2, 3, 4, 5, 6, 7, 8 ... 32 "loop: sw a4,0(a5)\n" // ...40 "slli a4,a4,0x1\n" // ...44 "addi a2,a2,-1\n" // ...48 "bnez a2,loop\n" // ...4C ----> 104 115 127 139 151 163 175 187...475 ); +11 +12 +12 +12 +12 +12 +12...91+N*12
| | | | |
В данном случае сдвигается влево 32-битное целое, взятое по адресу 8 - вывод каждого бита занимает ровно 12 тактов. Так как на предустановку уходит какое-то время, то начинать это делать надо не на 463м такте, а раньше...
|
09 Jul 2023 04:34 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Пытаюсь разобраться в том какой всё-таки размер у кеша инструкций в этой версии VexRiscv. Тот же код, что выше (плюс кое-какой набор инструкций, используемый для замера продолжительности работы): | | | | Code: // ...34 f00057b7 lui a5,0xf0005 // ...38 00c78793 addi a5,a5,12 # f000500c <_fdata_rom+0xe0003cb4> // ...3C 00100713 li a4,1 // ...40 00e7a023 sw a4,0(a5) <<<<<<<<<<<< МЕРЯЕМ ОТ СИХ // ...44 f00057b7 lui a5,0xf0005 // ...48 01078793 addi a5,a5,16 # f0005010 <_fdata_rom+0xe0003cb8> // ...4C 0007a783 lw a5,0(a5) // ...50 00078713 mv a4,a5 // ...54 00e02823 sw a4,16(zero) # 10 <i1.2347>
asm volatile( "nop\n" // ...58 "nop\n" // ...5C "nop\n" // ...60 "lw a4,8(zero)\n"// ...64 "lui a5,0x26000\n"// ...58 "addi a5,a5,12\n" // ...6C "li a2,32\n" // ...70 <<< N= 1, 2, 3, 4, 5, 6, 7, 8 ... 32 "loop: sw a4,0(a5)\n" // ...74 "slli a4,a4,0x1\n" // ...78 "addi a2,a2,-1\n" // ...7C "bnez a2,loop\n" // ...80 ----> 104 115 127 139 151 163 175 187...475 ); +11 +12 +12 +12 +12 +12 +12...91+N*12
// ...84 f00057b7 lui a5,0xf0005 // ...88 00c78793 addi a5,a5,12 # f000500c <_fdata_rom+0xe0003cb4> // ...8C 00100713 li a4,1 // ...90 00e7a023 sw a4,0(a5) <<<<<<<< ДО СИХ...
| | | | |
при любом N выполняется дольше на 4 такта, чем вот такой: | | | | Code: // ...34 f00057b7 lui a5,0xf0005 // ...38 00c78793 addi a5,a5,12 # f000500c <_fdata_rom+0xe0003cb4> // ...3C 00100713 li a4,1 // ...40 00e7a023 sw a4,0(a5) <<<<<<<<<<<< МЕРЯЕМ ОТ СИХ // ...44 f00057b7 lui a5,0xf0005 // ...48 01078793 addi a5,a5,16 # f0005010 <_fdata_rom+0xe0003cb8> // ...4C 0007a783 lw a5,0(a5) // ...50 00078713 mv a4,a5 // ...54 00e02823 sw a4,16(zero) # 10 <i1.2347>
asm volatile( "nop\n" // ...58 "nop\n" // ...5C "nop\n" // ...60 "nop\n" // ...64 "nop\n" // ...68 "nop\n" // ...6C "lw a4,8(zero)\n"// ...70 "lui a5,0x26000\n"// ...74 "addi a5,a5,12\n" // ...78 "li a2,32\n" // ...7C <<< N= 1, 2, 3, 4 ... 32 "loop: sw a4,0(a5)\n" // ...80 "slli a4,a4,0x1\n" // ...84 "addi a2,a2,-1\n" // ...88 "bnez a2,loop\n" // ...8C ----> 99 111 123 135...471 (-4) ); +12 +12 +12...87+N*12
// ...90 f00057b7 lui a5,0xf0005 // ...94 00c78793 addi a5,a5,12 # f000500c <_fdata_rom+0xe0003cb4> // ...98 00100713 li a4,1 // ...9C 00e7a023 sw a4,0(a5) <<<<<<<< ДО СИХ...
| | | | |
И это нее смотря на то, что в последнем на ТРИ NOP-а больше! P.S. А вообще при разном количестве нопов в начале асмового блока получаеются вот такие времена (при N=32): Как можно видеть между 0 и 8 разница 28 тактов, что вполне соотносится с тестом на голимые нопы (9 инструкций обёртка плюс N нопов): (при любом сдвиге 8 нопов подряд занимают 28 тактов)
|
12 Jul 2023 21:50 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Короче выходит, что из памяти действительно читается по 8 инструкций, однако при прохождении этих 8 инструкций будет вычитано следующие 8 ( без очистки предыдущих 8 ) и если код крутится в пределах этих 16 инструкций (64 байта), то никаких новых вычиток из памяти производится не будет!...
|
13 Jul 2023 00:17 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Покопался в верилоговских сырках проца: https://github.com/efabless/caravel_mgmt_soc_gf180mcu/blob/main/verilog/rtl/VexRiscv_MinDebugCache.vРазмер кеша там точно 16 слов: Однако заполняет он их хитро: Получается, что 5й бит адреса вычитанной последовательности слов управляет тем в какую половинку кэша инструкций будут писаться вычитываемые 8 слов: Соответственно в кеше инструкций всегда сидят 16 инструкций подряд, однако половинки кеша перемежаются - следующие 8 инструкций затирают позапредыдущие 8 инструкций, оставляя предыдущие 8 инструкций - вобщем как-то так...
|
13 Jul 2023 22:28 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22730 Location: Silicon Valley
|
Пишут вот такой разъёмчик тут стоит: https://www.lcsc.com/product-detail/Card-Edge-Connectors_TE-Connectivity-2199230-4_C2977809.htmlДумаю понаделать своих платок (попроще) чтобы воткнуть туда все 20 доче-платок, что у меня есть А потом может дойду и до распаивания собственных доче-платок, чтобы припаять туда 200+ чипов Caravel, что у меня есть
|
17 Jul 2023 23:36 |
|
|
Who is online |
Users browsing this forum: No registered users and 8 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|