Explorar o código

Fixed rom & pc timing and compiler

There was timing issue with ROM and program counter that been fixed by
taking pcn (pc next) value instead of waiting for ff. Also fixed
compiler invalid label address reading with move instruction.
Min %!s(int64=6) %!d(string=hai) anos
pai
achega
44db81d413

+ 6 - 0
.gitignore

@@ -10,8 +10,14 @@
 *.log
 *.out
 *.synctex.gz
+*.mem
+*.mif
+*.ver
+modelsim.ini
+__pycache__
 msim_transcript
 rtl_work/
+simulation/
 .idea
 .qsys_edit/
 db/

+ 0 - 56
src/blocks/instr_mem.sv

@@ -1,56 +0,0 @@
-module instr_rom(addr, instr);
-	parameter FILE = "";	
-	parameter WIDTH=8, LENGTH=256, OUTMUL=2;
-	parameter ADDR_WIDTH = $clog2(LENGTH);
-
-	input  wire [ADDR_WIDTH-1:0]   addr;
-	output reg  [WIDTH*OUTMUL-1:0] instr;
-	
-	initial $display("Instruction ROM %0dx%0dbit, size of %0dB loaded from %s", WIDTH, ADDR_WIDTH, LENGTH*WIDTH/8, FILE);
-	logic [WIDTH-1:0] rom [LENGTH-1:0];
-	initial if(FILE != "") $readmemh(FILE, rom);
-	initial begin
-		 $display("Instruction ROM dump");
-		 for (int i=0; i < LENGTH; i+=32) begin
-			$write("%h:", i);
-			for(int j=0; j<32 && j+i < LENGTH; j++)
-		 		$write(" %h", rom[i+j]);
-			$display(" :%h", i);
-		end
-	end
- 
-	always_comb begin
-		for (int i=0; i<OUTMUL;i++) 
-				instr[WIDTH*i+:WIDTH] = (addr+i >= LENGTH) ? '0 : rom[addr + i];
-	end
-endmodule
-
-`timescale 1ns / 1ns
-module instr_rom_tb;
-	reg [15:0] addr;
-	reg [15:0] instr;
-
-	instr_rom #("../../memory/rom_test.mem", 8, 256, 2, 16) rom0(addr, instr);
-
-	initial begin
-		addr = 'h0000;
-		#10ns;
-		assert(instr == 'h0100);
-		addr = 'h0001;
-		#10ns;
-		assert(instr == 'h0201);
-		addr = 'h0002;
-		#10ns;
-		assert(instr == 'h0302);
-		addr = 'h0003;
-		#10ns;
-		assert(instr == 'h0403);
-		addr = 'h00ff;
-		#10ns;
-		assert(instr == 'h00ff);
-		addr = 'haaff;
-		#10ns;
-		assert(instr == 'h0000);
-	end
-
-endmodule

+ 0 - 18
src/blocks/instr_mem_wr.sv

@@ -1,18 +0,0 @@
-//module instr_rom_wr(clk, addr, instr, wr_en, wr_data);
-module rom(addr, q);
-	parameter PROGRAM="";
-	parameter WIDTH=8, SIZE=1024;
-	parameter ADDR_WIDTH = $clog2(SIZE);
-	
-	//input  reg 	clk, wr_en;
-	//input reg [WIDTH-1:0] wr_data;
-	input  wire [ADDR_WIDTH-1:0]   addr;
-	output  reg  [WIDTH-1:0] q;
-	
-	logic [WIDTH-1:0] rom [ADDR_WIDTH-1:0];
-	initial $readmemh(PROGRAM, rom);
-	//always_ff@(posedge clk) if(wr) rom[addr] <= instr; 	
-
-	always_comb q[WIDTH-1:0] = rom[addr];
-endmodule
-

+ 3 - 0
src/blocks/rom.sv

@@ -136,6 +136,9 @@ module rom (
 		pseudo_rom#({PROGRAM, "_1.mem"}) rom1(addr1, clock, q1);
 		pseudo_rom#({PROGRAM, "_2.mem"}) rom2(addr2, clock, q2);
 		pseudo_rom#({PROGRAM, "_3.mem"}) rom3(addr3, clock, q3);
+		// Currently read address (for debugging)
+		reg [11:0] ff_addr;
+		always_ff@(posedge clock) ff_addr <= address;
 	`endif
 
 endmodule

+ 1 - 1
src/risc/controller.csv

@@ -34,7 +34,7 @@
       BZ,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
     CALL,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      1,         2,SO_MEML ,  ST_SUB,  PC_IMM 
      RET,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      1,      0,         2,SO_MEML ,  ST_ADD,  PC_MEM 
-    JUMP,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         1,SO_MEML , ST_NONE,  PC_IMM
+    JUMP,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         2,SO_MEML , ST_NONE,  PC_IMM
     RETI,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      1,      0,         2,SO_MEML ,  ST_SUB,  PC_MEM 
      CLC,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 
     SETC,   ALU_NONE,  SB_NONE,         0,  SR_NONE,      0,      0,         0,SO_MEML , ST_SKIP, PC_NONE 

+ 2 - 2
src/risc/controller.sv

@@ -526,7 +526,7 @@ module controller8(
             cdi.selr    = SR_NONE;
             mem_rd      = 0;
             mem_wr      = 1;
-            cdi.isize   = 1;
+            cdi.isize   = 2;
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_SUB;
             cdi.pcop    = PC_IMM;
@@ -556,7 +556,7 @@ module controller8(
             cdi.selr    = SR_NONE;
             mem_rd      = 0;
             mem_wr      = 0;
-            cdi.isize   = 1;
+            cdi.isize   = 3;
             cdi.selo    = SO_MEML;
             cdi.stackop = ST_NONE;
             cdi.pcop    = PC_IMM;

+ 7 - 6
src/risc/datapath.sv

@@ -63,11 +63,12 @@ module datapath8(
 
 	logic bconst; // Use immediate to branch
 	word pc_off; // Program counter offset
-	reg [15:0] pcn, pca; // Program Counter Previous, to add
+	reg [15:0] pcn, pca, pcx; // Program Counter Previous, to add
 	always_ff@(posedge clk) begin
-			if(rst) pc <= 0; 
-			else pc <= pcn;
+			if(rst) pcx <= 0; 
+			else pcx <= pcn;
 	end
+	assign pc = (rst) ? 0 : pcn;
 	
 	always_comb begin
 		bconst = 0;  // FIXME: temporary
@@ -78,11 +79,11 @@ module datapath8(
 			(~cdi.isize[1]&~cdi.isize[0])|(cdi.isize[1]&~cdi.isize[0])
 		}; // Adding 1 to 2bit value.
 		case(cdi.pcop)
-			PC_NONE: pcn = pc + pc_off;
+			PC_NONE: pcn = pcx + pc_off;
 			PC_MEM : pcn = mem_rd;
 			PC_IMM : pcn = {imm[7:0], imm[15:8]};
 			PC_IMM2: pcn = {imm[15:8], imm[23:16]};
-			default: pcn = pc;
+			default: pcn = pcx;
 		endcase
 		//pca = (bconst) ? {imm[7:0], imm[15:8]} : pc;
 		//pcn = pca + pc_off;
@@ -140,7 +141,7 @@ module datapath8(
 
 	// COM Write
 	assign com_wr = (cdi.selo == SO_COM) ? r1 : '0;
-	assign com_addr = imm[7:0];
+	assign com_addr = (cdi.selo == SO_COM) ? imm[7:0] : '0;
 	//assign com_addr = 8'h06;
 	//assign com_wr = pc[7:0];
 

+ 12 - 8
tools/asm_compiler.py

@@ -155,10 +155,14 @@ class CompObject:
         self.line_num = line_num
         self.code = []
         self.code_ref = 0
-
-    def compile(self):
         self.code = self.instr.compile(self.operands)
-        return self.code
+
+    def instr_len(self):
+        if hasattr(self.instr, 'get_imm_operands'):
+            o = getattr(self.instr, 'get_imm_operands')
+            return o(self.operands)
+        else:
+            return self.instr.length
 
 
 class Compiler:
@@ -308,7 +312,7 @@ class Compiler:
             label = linespl[0]
             if label in self.labels:
                 raise CompilingError(f"Label {label} duplicate")
-            self.labels[label] = (self.caddress).to_bytes(self.address_size, self.order)
+            self.labels[label] = self.caddress.to_bytes(self.address_size, self.order)
         if line.startswith('%define'):
             sp = list(filter(None, line.split(' ', 3)))
             if len(sp) != 3:
@@ -339,14 +343,14 @@ class Compiler:
                 co = self.__precompile(line)
                 if co is not None:
                     co.line_num = lnum
-                    self.caddress += co.instr.length
+                    self.caddress += co.instr_len()
                     instr.append(co)
             except CompilingError as e:
                 failure = True
                 print(f"ERROR {file}:{lnum}: {e.message}")
         for co in instr:
             try:
-                binary += co.compile()
+                binary += co.code
             except CompilingError as e:
                 failure = True
                 print(f"ERROR {file}:{co.line_num}: {e.message}")
@@ -379,12 +383,12 @@ def convert_to_binary(data):
 
 def convert_to_mem(data):
     x = b''
-    fa = f'0{math.ceil(int(math.log2(len(data)))/4)}x'
+    fa = f'0{math.ceil(math.ceil(math.log2(len(data)))/4)}x'
     a = [format(d, '02x') for d in data]
     for i in range(int(len(a) / 8) + 1):
         y = a[i * 8:(i + 1) * 8]
         if len(y) > 0:
-            x += (' '.join(y) + '  // ' + format(i*8, fa) + '\n').encode()
+            x += (' '.join(y) + ' '*((8-len(y))*3) + '  // ' + format((i*8-1)+len(y), fa) + '\n').encode()
     return x
 
 

+ 85 - 0
tools/bs_test.asm

@@ -0,0 +1,85 @@
+    global start
+    section .text
+start:
+    mov
+message: db   "Hello Wolrd", 0
+
+
+;CPY $re 0xFF
+;CPY $rb 0x01
+;CPY $ra 'H'
+;SW $ra $re
+;
+;CPY $ra '3'
+;node3:
+;LW $rc $re
+;JEQ $rc $rb node3
+;SW $ra $re
+;
+;CPY $ra 'l'
+;nodeL1:
+;LW $rc $re
+;JEQ $rc $rb nodeL1
+;SW $ra $re
+;
+;nodeL2:
+;LW $rc $re
+;JEQ $rc $rb nodeL2
+;SW $ra $re
+;
+;CPY $ra '0'
+;node0:
+;LW $rc $re
+;JEQ $rc $rb node0
+;SW $ra $re
+;
+;CPY $ra '_'
+;nodeS:
+;LW $rc $re
+;JEQ $rc $rb nodeS
+;SW $ra $re
+;
+;CPY $ra 'P'
+;nodeP:
+;LW $rc $re
+;JEQ $rc $rb nodeP
+;SW $ra $re
+;
+;CPY $ra 'r'
+;nodeR:
+;LW $rc $re
+;JEQ $rc $rb nodeR
+;SW $ra $re
+;
+;CPY $ra '1'
+;node1:
+;LW $rc $re
+;JEQ $rc $rb node1
+;SW $ra $re
+;
+;CPY $ra 'c'
+;nodeC:
+;LW $rc $re
+;JEQ $rc $rb nodeC
+;SW $ra $re
+;
+;CPY $ra 'k'
+;nodeK:
+;LW $rc $re
+;JEQ $rc $rb nodeK
+;SW $ra $re
+;
+;CPY $ra 0x0A
+;nodeLF:
+;LW $rc $re
+;JEQ $rc $rb nodeLF
+;SW $ra $re
+;
+;CPY $ra 0x0D
+;nodeCR:
+;LW $rc $re
+;JEQ $rc $rb nodeCR
+;SW $ra $re
+;
+;stop:
+;JMP stop

+ 8 - 1
tools/risc8asm.py

@@ -13,13 +13,20 @@ asmc.add_reg('r3', 3)
 
 
 class MoveInstr(compiler.Instruction):
+    def get_imm_operands(self, operands):
+        try:
+            self.compiler.decode_reg(operands[1])
+            return 1
+        except compiler.CompilingError:
+            return 2
+
     def compile(self, operands):
         regs = [0, 0]
         imm = []
         regs[0] = self.compiler.decode_reg(operands[0])
         try:
             regs[1] = self.compiler.decode_reg(operands[1])
-            self.imm_operands = 0
+            self.imm_operands = 0   # Assuming this gonna be changed every time
         except compiler.CompilingError:
             regs[1] = regs[0]
             self.imm_operands = 1