nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 27 Apr 2024 13:22



Reply to topic  [ 62 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Гуглосиликон на халяву! 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Впредь надо будет интерфейс шины Wishbone задействовать - проц Caravel может с пользовательским дизайном через эту шину общаться - можно на разные адреса вешать регистры и вообще память цеплять - вот тут подробности с примером: https://vlsi.jp/Introduction_to_OpenMPW.html

Attachment:
Screenshot from 2023-06-30 22-39-15.png
Screenshot from 2023-06-30 22-39-15.png [ 95.18 KiB | Viewed 8504 times ]


Пример на верилоге с тремя регистрами, доступными на запись и на чтение:
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

_________________
:dj: https://mastodon.social/@Shaos


30 Jun 2023 22:40
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Научился прошивать тестовую программку в девборду :mrgreen:
https://github.com/efabless/caravel_board/blob/main/gf180/blink/blink.c

Code:
python3.8 ../util/caravel_hkflash.py blink.hex
Success: Found one matching FTDI device at ftdi://ftdi:232h:1:15/1
 
Caravel data:
   mfg        = 0456
   product    = 20
   project ID = 180058d2
 
Resetting Flash...
status = 0x00
 
JEDEC = b'ef4016'
Erasing chip...
done
status = 0x0
setting address to 0x0
addr 0x0: flash page write successful
addr 0x100: flash page write successful
addr 0x200: flash page write successful
addr 0x300: flash page write successful
addr 0x400: flash page write successful
addr 0x500: flash page write successful
addr 0x600: flash page write successful

total_bytes = 1652
status reg_1 = 0x0
status reg_2 = 0x2
************************************
verifying...
************************************
status reg_1 = 0x0
status reg_2 = 0x2
setting address to 0x0
addr 0x0: read compare successful
addr 0x100: read compare successful
addr 0x200: read compare successful
addr 0x300: read compare successful
addr 0x400: read compare successful
addr 0x500: read compare successful
addr 0x600: read compare successful

total_bytes = 1652
pll_trim = b'4b'

python3.8 ../util/caravel_hkstop.py
Success: Found one matching FTDI device at ftdi://ftdi:232h:1:15/1

Теперь можно начинать писать свою программку для тестирования пользовательских внутренностей...

_________________
:dj: https://mastodon.social/@Shaos


01 Jul 2023 00:06
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
На борту девборды установлен генератор 10 МГц - и похоже чип на такой частоте и работает т.к. вот такая функция:
Code:
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;
   }

}
будучи вызвана с аргументом 5000000 выполняется ровно полсекунды

_________________
:dj: https://mastodon.social/@Shaos


01 Jul 2023 00:24
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Чтобы USB-шнурок мог использоваться не только для прошивки, но и для последовательного взаимодействия нужно поставить вот этот джампер:

Attachment:
GF180-E5-serial.jpg
GF180-E5-serial.jpg [ 324.94 KiB | Viewed 8455 times ]

После этого заработало
Code:
 print("Hello World !!");
на скорости 9600 :dj:

_________________
:dj: https://mastodon.social/@Shaos


01 Jul 2023 14:19
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Люди нашли способ настраивать входы-выходы так, чтобы можно было из проца подавать уровни на входы пользовательского модуля и читать выходы - теперь можно полноценно тестироваться :)

_________________
:dj: https://mastodon.social/@Shaos


01 Jul 2023 23:43
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Shaos wrote:
Всё работает, кроме C-гейта что внизу схемы :(


Написал программку для встроенного проца - всё работает как надо, включая C-гейт :mrgreen:

_________________
:dj: https://mastodon.social/@Shaos


02 Jul 2023 01:27
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Прошивальная питоновская утилитка у них периодически сбоила, поэтому я её им пофиксил и заслал пул-реквест :roll:

https://github.com/efabless/caravel_board/pull/85

P.S. Иногда оно всё же перехлёстывается - надо переписывать...

_________________
:dj: https://mastodon.social/@Shaos


04 Jul 2023 01:02
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Shaos wrote:
Shaos wrote:
Всё работает, кроме C-гейта что внизу схемы :(


Написал программку для встроенного проца - всё работает как надо, включая C-гейт :mrgreen:

Под спойлером текст программки:

 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 (я только добавил туда расшифровку входов и выходов):
Code:
Hello World !!
CLK -------------------------------.
DATA -----------------------------.|
CLK2 ----------------------------.||
SET ----------------------------,|||
RESET ------------------------. ||||
NAND1 -----------------------.| ||||      RS D2D1
NAND2 ----------------------.|| ||||    _ _  _ _
DATA2 ---------------------.||| ||||    COQQ QQQQ
Counter:  000 : 00b9003d : 0000 0000 -> 1011 1001
Counter:  001 : 003a013d : 0000 0001 -> 0011 1010
Counter:  002 : 00ba003d : 0000 0000 -> 1011 1010
Counter:  003 : 00ba023d : 0000 0010 -> 1011 1010
Counter:  004 : 0039033d : 0000 0011 -> 0011 1001
Counter:  005 : 00b9023d : 0000 0010 -> 1011 1001
Counter:  006 : 00b9003d : 0000 0000 -> 1011 1001
Counter:  007 : 003a013d : 0000 0001 -> 0011 1010
Counter:  008 : 00ba003d : 0000 0000 -> 1011 1010
Counter:  009 : 00ba023d : 0000 0010 -> 1011 1010
Counter:  010 : 0039033d : 0000 0011 -> 0011 1001
Counter:  011 : 00b9023d : 0000 0010 -> 1011 1001
Counter:  012 : 00b9003d : 0000 0000 -> 1011 1001
Counter:  013 : 00b9043d : 0000 0100 -> 1011 1001
Counter:  014 : 00b9003d : 0000 0000 -> 1011 1001
Counter:  015 : 00b9023d : 0000 0010 -> 1011 1001
Counter:  016 : 00b5063d : 0000 0110 -> 1011 0101
Counter:  017 : 00b5023d : 0000 0010 -> 1011 0101
Counter:  018 : 00b5003d : 0000 0000 -> 1011 0101
Counter:  019 : 00b9043d : 0000 0100 -> 1011 1001
Counter:  020 : 00b9003d : 0000 0000 -> 1011 1001
Counter:  021 : 00b9023d : 0000 0010 -> 1011 1001
Counter:  022 : 00b5063d : 0000 0110 -> 1011 0101
Counter:  023 : 00b5023d : 0000 0010 -> 1011 0101
Counter:  024 : 00b9123d : 0001 0010 -> 1011 1001
Counter:  025 : 00b9023d : 0000 0010 -> 1011 1001
Counter:  026 : 00b9003d : 0000 0000 -> 1011 1001
Counter:  027 : 00b5083d : 0000 1000 -> 1011 0101
Counter:  028 : 00b5003d : 0000 0000 -> 1011 0101
Counter:  029 : 0095603d : 0110 0000 -> 1001 0101
Counter:  030 : 00a5203d : 0010 0000 -> 1010 0101
Counter:  031 : 00a5603d : 0110 0000 -> 1010 0101
Counter:  032 : 0095403d : 0100 0000 -> 1001 0101
Counter:  033 : 0095603d : 0110 0000 -> 1001 0101
Counter:  034 : 0095623d : 0110 0010 -> 1001 0101
Counter:  035 : 00d5e23d : 1110 0010 -> 1101 0101
Counter:  036 : 00d5623d : 0110 0010 -> 1101 0101
Counter:  037 : 0095603d : 0110 0000 -> 1001 0101
Counter:  038 : 0095623d : 0110 0010 -> 1001 0101
Counter:  039 : 00d5e23d : 1110 0010 -> 1101 0101
Counter:  040 : 00d5e03d : 1110 0000 -> 1101 0101
Counter:  041 : 0095603d : 0110 0000 -> 1001 0101

_________________
:dj: https://mastodon.social/@Shaos


04 Jul 2023 21:07
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
В чипах Efabless сделанных по техпроцессу GF180 в качестве микроконтроллера встроена корка VexRiscv, что есть настраиваемая реализация RISC-V (см. https://github.com/SpinalHDL/VexRiscv). Она выполняет код прямо из последовательной SPI-флеши (на девборде стоит 4МБ флеш, способная работать на частотах до 133 МГц) и по слухам в корке есть какой-то маленький кэш инструкций (надо проверить). По памяти раскладка такая (вытащено из h-файла сгенерённого построителем корки, т.е. должно быть корректно):
Code:
VEXRISCV_DEBUG  0xf00f0000 0x100      (256)
SRAM            0x00000000 0x800      (2048)
FLASH           0x10000000 0x1000000  (16777216)
MPRJ            0x30000000 0x10000000 (268435456)
HK              0x26000000 0x300000   (3145728)
CSR             0xf0000000 0x10000    (65536)
FLASH это адресное пространство программ, которое маппится на SPI-флеш (из 16-мегабайтного адресного пространства реально задействовано 4МБ);
SRAM это реально присутствующее в чипе ОЗУ размером всего 2КБ - там располагается память данных;
HK это область портов ввода-вывода, их настройки и чтения-записи;
MPRJ это адресное пространство открываемое внутрь пользовательской логики по шине Wishbone (выше на этой странице есть пример реализации 3 регистров в этом адресном пространстве) - в моих чипах это адресное пространство не используется совсем.

Проц работает на частоте 10 МГц, но есть возможность поставить джампер, который запретит осциллятор девборды и тогда клок надо будет пускать извне через ногу xclk (люди пробовали разгонять чип до 25 МГц).

Последовательный порт на 9600 реализован через FTDI-чип и сразу идёт на USB гнездо (на линуксе оно обнаруживается как /dev/ttyUSB0 и работает через любую терминалку).

Проверил некоторые адреса, а именно первая глобальная переменная, первая переменная в функции main, сама функция main и функция isr (обработчик прерываний):
Code:
global addr 00000008
i addr 000007e4
main addr 10000d64
isr addr 10000178
Получается, что isr тоже сидит в последовательной флеше, а локальные переменные, сидящие в стеке, пододвинуты ближе к концу памяти данных.

P.S. Пытаюсь сравнить скорости исполнения из последовательного флеша и из памяти данных - можно создать глобальный массив 32-битных целых, скопировать туда какую-то функцию и запустить - в результате она будет работать существенно быстрее :)
Например:
Code:
int calc(void)
{
    static int i1,i2;
    reg_timer0_update = 1;  // latch current value
    i1 = reg_timer0_value; // МЕРЯЕМ ОТ СИХ
    global++;
    reg_timer0_update = 1;  // latch current value
    i2 = reg_timer0_value; // ДО СИХ
    return i1-i2;
}

Будучи запущенным из флеша код между сохранениями i1 и i2 (там примерно 12 инструкций) выполняется за 1104 такта, а из памяти данных - только 86 (что тоже многовато).
Если поставить два global++ вместо одного (примерно 15 инструкций), то числа уже 1119 и 98 - получается один инкремент глобальной переменной в ОЗУ занимает 12 тактов, что есть 3 инструкции:
Code:
10000d24:       01002783                lw      a5,16(zero) # 10 <_edata>
10000d28:       00178713                addi    a4,a5,1
10000d2c:       00e02823                sw      a4,16(zero) # 10 <_edata>
Значит одна инструкция запускается тут за 4 такта!
А вот если добавить третий global++ (примерно 18 инструкций), то числа уже станут 2192 и 130 соответственно (уже на 32 такта больше???).
Если убрать global++ вовсе (тогда между замерами станет 9 инструкций), то цифры становятся 1095 и 53.
Так что похоже кэш инструкций там таки есть и он перезаписывается примерно после 16 инструкций:
Code:
 9 : 1095 :  53 : ideal 36 (+17)
12 : 1104 :  86 : ideal 48 (+38)
15 : 1119 :  98 : ideal 60 (+38)
18 : 2192 : 130 : ideal 72 (+58)


P.P.S. Выровнял смещение для скопированной функции в памяти данных так, чтобы было как во флеше (первое сохранение текущего счётчика тактов приходится на начало 64-байтного блока) - теперь стало так (замеры только для ОЗУ):
Code:
 9 :  55 : ideal 36 (+19)
12 :  64 : ideal 48 (+16)
15 :  79 : ideal 60 (+19)
18 : 112 : ideal 72 (+40)

Ещё интересное наблюдение - 3 nop-a занимают меньше тактов (на 6 меньше), чем эти 3 инструкции:
Code:
10000d24:       01002783                lw      a5,16(zero) # 10 <_edata>
10000d28:       00178713                addi    a4,a5,1
10000d2c:       00e02823                sw      a4,16(zero) # 10 <_edata>
Хотя казалось бы, это RISC - всё должно быть одинаково (если это не передача управления), тем более NOP это на самом деле ADDI R0,R0,0 (хотя тут есть store инструкция - комнда sw, которая например в моей реализации была чуть дольше остальных)...

P.P.P.S. Вот исходники версии Caravel-проца, что ставится в GF180: https://github.com/efabless/caravel_mgmt_soc_gf180mcu/tree/main

_________________
:dj: https://mastodon.social/@Shaos


04 Jul 2023 21:36
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Вообще два раза подряд global++ без оптимизации компилируется вот так:
Code:
       01002783                lw      a5,16(zero) # 10 <_edata>
       00178713                addi    a4,a5,1
       00e02823                sw      a4,16(zero) # 10 <_edata>
       01002783                lw      a5,16(zero) # 10 <_edata>
       00178713                addi    a4,a5,1
       00e02823                sw      a4,16(zero) # 10 <_edata>

т.е. сразу после сохранения переменной в памяти идёт чтение переменной из этой памяти, что может вызывать проблемы у RISC-процессоров - возможно корка ждёт, когда переменная будет записана прежде чем её прочитает, а может и не ждёт...

По тактам значит получается так:
Code:
 # : FLASH        :  SRAM
----------------------------------
 9 : 1095         :  55
12 : 1104 (+9)    :  64 (+9)
15 : 1119 (+15)   :  79 (+15)
18 : 2192 (+1073) : 112 (+33)

Как можно видеть переход от 9 к 12 и потом к 15 инструкциям отличается на одинаковое кол-во тактов для флаша и для срама, а вот зашкал за 16 сильно длиннее у флеша т.к. там идёт заполнение кеша инструкций из SPI-флеша (а может глубина кеша 8, а не 16 и поэтому при 9 сразу много?).

P.S. Потестил добавление NOP-ов по одному:
Code:
 9 : 55
10 : 52  (-3)
11 : 57  (+5)
12 : 58  (+1)
13 : 59  (+1)
14 : 60  (+1)
15 : 77  (+17)
16 : 78  (+1)
17 : 83  (+5)
18 : 80  (-3)
19 : 85  (+5)
20 : 86  (+1)
21 : 87  (+1)
22 : 88  (+1)
23 : 105 (+17)

Тут отчётливо видно, что кэш инструкций вмещает в себя 8 команд.

P.P.S. Вот ещё замеры LW и SW:
Code:
LWs:

 9 : 55
10 : 55 (0)
11 : 60 (+5)
12 : 62 (+2)
13 : 65 (+3)
14 : 68 (+3)
15 : 71 (+3)
16 : 92 (+21)
17 : 99 (+7)
18 : 98 (-1)
19 : 103 (+5)
20 : 105 (+2)

SWs:

 9 : 55
10 : 55 (0)
11 : 59 (+4)
12 : 60 (+1)
13 : 63 (+3)
14 : 66 (+3)
15 : 69 (+3)
16 : 90 (+21)

_________________
:dj: https://mastodon.social/@Shaos


05 Jul 2023 21:51
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Думаю сгенерить NTSC-сигнал программно на Caravel

На 5 МГц 19 лет назад я так времянки раскладывал:
Code:
Frame (in lines) 262:
20-sync 24-preframe 192-frame 26-postframe
Line (in ticks) 318:
24-low 30-high 256-signal 8-high

Для 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м такте, а раньше...

_________________
:dj: https://mastodon.social/@Shaos


09 Jul 2023 04:34
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Пытаюсь разобраться в том какой всё-таки размер у кеша инструкций в этой версии 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):
Code:
0 -> 466
1 -> 467
2 -> 469
3 -> 475 (первоначальный вариант в предыдущем сообщении)
4 -> 481
5 -> 483
6 -> 471 (эта самая непонятка)
7 -> 492
8 -> 494

Как можно видеть между 0 и 8 разница 28 тактов, что вполне соотносится с тестом на голимые нопы (9 инструкций обёртка плюс N нопов):
Code:
 9 : 55
10 : 52  (-3)
11 : 57  (+5)
12 : 58  (+1)
13 : 59  (+1)
14 : 60  (+1)
15 : 77  (+17)
16 : 78  (+1)
17 : 83  (+5)
18 : 80  (-3)
19 : 85  (+5)
20 : 86  (+1)
21 : 87  (+1)
22 : 88  (+1)
23 : 105 (+17)
(при любом сдвиге 8 нопов подряд занимают 28 тактов)

_________________
:dj: https://mastodon.social/@Shaos


12 Jul 2023 21:50
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Короче выходит, что из памяти действительно читается по 8 инструкций, однако при прохождении этих 8 инструкций будет вычитано следующие 8 ( без очистки предыдущих 8 ) и если код крутится в пределах этих 16 инструкций (64 байта), то никаких новых вычиток из памяти производится не будет!...

_________________
:dj: https://mastodon.social/@Shaos


13 Jul 2023 00:17
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Покопался в верилоговских сырках проца:
https://github.com/efabless/caravel_mgmt_soc_gf180mcu/blob/main/verilog/rtl/VexRiscv_MinDebugCache.v
Размер кеша там точно 16 слов:
Code:
   (* ram_style = "block" *) reg [31:0] banks_0 [0:15];
Однако заполняет он их хитро:
Code:
 wire       [3:0]    lineLoader_write_data_0_payload_address;
 ...
       banks_0[lineLoader_write_data_0_payload_address] <= lineLoader_write_data_0_payload_data;
 ...
   assign lineLoader_write_data_0_payload_address = {lineLoader_address[5 : 5],lineLoader_wordIndex};
Получается, что 5й бит адреса вычитанной последовательности слов управляет тем в какую половинку кэша инструкций будут писаться вычитываемые 8 слов:
Code:
   (* keep , syn_keep *) reg        [31:0]   lineLoader_address /* synthesis syn_keep = 1 */ ;
 ...
   (* keep , syn_keep *) reg        [2:0]    lineLoader_wordIndex /* synthesis syn_keep = 1 */
Соответственно в кеше инструкций всегда сидят 16 инструкций подряд, однако половинки кеша перемежаются - следующие 8 инструкций затирают позапредыдущие 8 инструкций, оставляя предыдущие 8 инструкций - вобщем как-то так...

_________________
:dj: https://mastodon.social/@Shaos


13 Jul 2023 22:28
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22606
Location: Silicon Valley
Reply with quote
Shaos wrote:
Дочка даже прикручивается винтиком :)

Image
Пишут вот такой разъёмчик тут стоит:

https://www.lcsc.com/product-detail/Card-Edge-Connectors_TE-Connectivity-2199230-4_C2977809.html

Думаю понаделать своих платок (попроще) чтобы воткнуть туда все 20 доче-платок, что у меня есть :mrgreen:

А потом может дойду и до распаивания собственных доче-платок, чтобы припаять туда 200+ чипов Caravel, что у меня есть :roll:

_________________
:dj: https://mastodon.social/@Shaos


17 Jul 2023 23:36
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 62 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

Who is online

Users browsing this forum: No registered users and 61 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

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.