Просмотр исходного кода

OISC ROM

New ROM design for OISC. Memory now uese 3 M9K blocks to store 2x13bit
instructions. LSB of 3 cell memory is used for parity check (TBA).
Min 5 лет назад
Родитель
Сommit
09ba0b4397
6 измененных файлов с 204 добавлено и 110 удалено
  1. 6 2
      src/blocks/rom.sv
  2. 5 84
      src/oisc/cpu.sv
  3. 3 3
      src/oisc/oisc.sv
  4. 107 0
      src/oisc/romblock.sv
  5. 32 4
      tools/asm_compiler.py
  6. 51 17
      tools/oisc8asm.py

+ 6 - 2
src/blocks/rom.sv

@@ -78,17 +78,21 @@ module pseudo_rom(addr, clk, q);
 	parameter PROGRAM="";
 	parameter WIDTH=8;
 	parameter NUMWORDS=1024;
+	parameter BINARY=0;
 	localparam AWIDTH=$clog2(NUMWORDS);
 	
 	input  reg 	clk;
 	input  wire [AWIDTH-1:0] addr;
-	output  reg [WIDTH-1:0] q;
+	output reg [WIDTH-1:0] q;
 	
 	initial $display("Initialising ROM Memory: %s", PROGRAM);
 	
 	reg [AWIDTH-1:0] addr0;
 	logic [WIDTH-1:0] rom [NUMWORDS:0];
-	initial $readmemh(PROGRAM, rom);
+	initial begin
+		if(BINARY==0) $readmemh(PROGRAM, rom);
+		else $readmemb(PROGRAM, rom);
+	end
 	always_ff@(posedge clk) addr0 <= addr; 	
 	assign q = rom[addr0];
 

+ 5 - 84
src/oisc/cpu.sv

@@ -1,5 +1,10 @@
+`ifndef DEFINED
+`define DEFINED
 `include "oisc.sv"
 `include "../const.sv"
+`endif
+`include "romblock.sv"
+
 import oisc8_pkg::*;
 
 
@@ -25,90 +30,6 @@ module oisc8_cpu(processor_port port);
 
 endmodule
 
-module pc_block(IBus.port bus, IBus.iport port);
-
-	wire[`SAWIDTH+`DAWIDTH:0] instr;
-
-	assign port.imm = instr[`DAWIDTH+`SAWIDTH];
-	assign port.instr_dst = e_iaddr_dst'(instr[`DAWIDTH+`SAWIDTH-1:`SAWIDTH]);
-	assign port.instr_src = e_iaddr_src'(port.imm ? `SAWIDTH'd0 : instr[`SAWIDTH-1:0]);
-	
-	reg write_null;	
-	always_comb write_null = (bus.instr_src == `SAWIDTH'd0) & ~port.imm;
-	data_buf dbus0(bus, 0, write_null);	
-	data_buf dbus1(bus, instr[`DWIDTH-1:0], port.imm);	
-	//genvar i;
-	//generate 
-	//	for(i=0;i<`DWIDTH;i=i+1) begin : generate_imm_to_data
-	//		bufif1(bus.data[i], instr[i], port.imm);
-	//	end 
-	//endgenerate
-	
-	//generate 
-	//	for(i=0;i<`DWIDTH;i=i+1) begin : generate_null_to_data
-	//		bufif1(bus.data[i], 0, write_null);
-	//	end 
-	//endgenerate
-	
-	parameter PROGRAM = "";
-	reg[15:0] pc, pcn, pcr; // Program counter
-	reg[15:0] pointer;  // Instruction pointer accumulator
-	reg[7:0] comp_acc;  // Compare accumulator
-	reg comp_zero;
-
-	/* ====================
-	*       ROM BLOCK
-	   ==================== */
-	`ifdef SYNTHESIS
-	m9k_rom#(
-			.PROGRAM({PROGRAM, ".mif"}), 
-			.NAME("rom0"),
-			.WIDTH(16),
-			.NUMWORDS(2048)
-	)
-	`else
-	pseudo_rom#(
-			.PROGRAM({PROGRAM, ".mem"}), 
-			.WIDTH(16),
-	 		.NUMWORDS(2048)
-	) 
-	`endif
-		rom0(pc[12:0], bus.clk, instr[12:0]);
-
-
-	`ifndef SYNTHESIS
-	reg [15:0] pcp;  // Current program counter for debugging
-	`endif 
-
-	always_comb comp_zero = comp_acc == `DWIDTH'd0;
-	//assign pcn = comp_zero|bus.rst ? pointer : pc + 1;
-	assign pcn = pc + 1;
-	always_ff@(posedge bus.clk) begin
-		if(bus.rst) begin 
-			pcr <= 0;
-		end
-		else begin 
-			`ifndef SYNTHESIS
-			pcp <= pc;
-			`endif 
-			pcr <= pcn;
-		end
-	end
-	assign pc = ~comp_zero|bus.rst ? pcr: pointer; 	
-	PortReg#(.ADDR_SRC(BRPT0R), .ADDR_DST(BRPT0)) p_brpt0(
-			.bus(bus),.register(pointer[7:0]),.wr(),.rd()
-	);
-	PortReg#(.ADDR_SRC(BRPT1R), .ADDR_DST(BRPT1)) p_brpt1(
-			.bus(bus),.register(pointer[15:8]),.wr(),.rd()
-	);
-	PortInput#(.ADDR(BRZ), .DEFAULT(`DWIDTH'hFF)) p_brz(
-			.bus(bus),.data_from_bus(comp_acc)
-	);
-	PortOutput#(.ADDR(PC0)) p_pc0(.bus(bus),.data_to_bus(pcn[7:0]));
-	PortOutput#(.ADDR(PC1)) p_pc1(.bus(bus),.data_to_bus(pcn[15:8]));
-
-endmodule
-
 module oisc_com_block(IBus.port bus, processor_port port);
 	
 	// ========================

+ 3 - 3
src/oisc/oisc.sv

@@ -75,11 +75,11 @@ package oisc8_pkg;
 
 endpackage
 
-interface IBus(clk, rst, instr);
+interface IBus(input clk, rst);
 	import oisc8_pkg::*;
 	
-	input wire clk, rst;	
-	input wire[`SAWIDTH+`DAWIDTH:0] instr;
+	//input wire clk, rst;	
+	//input wire[`SAWIDTH+`DAWIDTH:0] instr;
 
 	wire[`DWIDTH-1:0] data;
 	logic imm;

+ 107 - 0
src/oisc/romblock.sv

@@ -0,0 +1,107 @@
+`ifndef DEFINED
+`define DEFINED
+`include "oisc.sv"
+`include "../const.sv"
+`endif
+
+import oisc8_pkg::*;
+
+module pc_block(IBus.port bus, IBus.iport port);
+	parameter PROGRAM = "";
+
+	wire[`SAWIDTH+`DAWIDTH:0] instr;
+
+	assign port.imm = instr[`DAWIDTH+`SAWIDTH];
+	assign port.instr_dst = e_iaddr_dst'(instr[`DAWIDTH+`SAWIDTH-1:`SAWIDTH]);
+	assign port.instr_src = e_iaddr_src'(port.imm ? `SAWIDTH'd0 : instr[`SAWIDTH-1:0]);
+	
+	reg write_null;	
+	always_comb write_null = (bus.instr_src == `SAWIDTH'd0) & ~port.imm;
+	data_buf dbus0(bus, `DWIDTH'd0, write_null);	
+	data_buf dbus1(bus, instr[`DWIDTH-1:0], port.imm);	
+	
+	wire[15:0] pcn;
+	reg[15:0] pc, pcr; // Program counter
+	reg[15:0] pointer;  // Instruction pointer accumulator
+	reg[7:0] comp_acc;  // Compare accumulator
+	reg comp_zero;
+	reg rst0, pc0; // delayed reset and lsb of pc
+
+	/* ====================
+	*       ROM BLOCK
+	   ==================== */
+	wire [26:0] instrBlock;
+	wire [12:0] instrA, instrB;
+	`ifdef SYNTHESIS
+	m9k_rom#(.PROGRAM({PROGRAM, "_0.mif"}),.NAME("rom0"),.WIDTH(9),.NUMWORDS(1024))
+		rom0(pc[10:1], bus.clk, instrBlock[26:18]);
+	m9k_rom#(.PROGRAM({PROGRAM, "_1.mif"}),.NAME("rom1"),.WIDTH(9),.NUMWORDS(1024))
+		rom1(pc[10:1], bus.clk, instrBlock[17:9]);
+	m9k_rom#(.PROGRAM({PROGRAM, "_2.mif"}),.NAME("rom2"),.WIDTH(9),.NUMWORDS(1024))
+		rom2(pc[10:1], bus.clk, instrBlock[8:0]);
+	`else
+	pseudo_rom#(.PROGRAM({PROGRAM, "_0.mem"}),.WIDTH(9),.NUMWORDS(1024),.BINARY(1)) 
+		rom0(pc[10:1], bus.clk, instrBlock[26:18]);
+	pseudo_rom#(.PROGRAM({PROGRAM, "_1.mem"}),.WIDTH(9),.NUMWORDS(1024),.BINARY(1)) 
+		rom1(pc[10:1], bus.clk, instrBlock[17:9]);
+	pseudo_rom#(.PROGRAM({PROGRAM, "_2.mem"}),.WIDTH(9),.NUMWORDS(1024),.BINARY(1)) 
+		rom2(pc[10:1], bus.clk, instrBlock[8:0]);
+	`endif
+	assign instrA = instrBlock[26:14];
+	assign instrB = instrBlock[13:1];
+	assign instr = pc0 ? instrA : instrB;
+
+	`ifndef SYNTHESIS
+	reg [15:0] pcp;  // Current program counter for debugging
+	always_ff@(posedge bus.clk) pcp <= pc;
+	`endif
+	
+
+	always_comb comp_zero = comp_acc == `DWIDTH'd0;
+	//assign pcn = comp_zero|bus.rst ? pointer : pc + 1;
+	assign pcn = pc + 1;
+	always_ff@(posedge bus.clk) begin
+		rst0 <= bus.rst;
+		if(bus.rst) begin 
+			pcr <= 16'd0;
+			pc0 <= 1'b0;
+		end else begin 
+			pcr <= pcn;
+			pc0 <= pc[0];
+		end
+	end
+	always_comb casez({comp_zero,bus.rst|rst0})
+		2'b00: pc = pcr;
+		2'b10: pc = pointer;
+		2'b?1: pc = 16'd0;
+	endcase
+
+	PortReg#(.ADDR_SRC(BRPT0R), .ADDR_DST(BRPT0)) p_brpt0(
+			.bus(bus),.register(pointer[7:0]),.wr(),.rd()
+	);
+	PortReg#(.ADDR_SRC(BRPT1R), .ADDR_DST(BRPT1)) p_brpt1(
+			.bus(bus),.register(pointer[15:8]),.wr(),.rd()
+	);
+	PortInput#(.ADDR(BRZ), .DEFAULT(`DWIDTH'hFF)) p_brz(
+			.bus(bus),.data_from_bus(comp_acc),.wr()
+	);
+	PortOutput#(.ADDR(PC0)) p_pc0(.bus(bus),.data_to_bus(pcn[7:0]),.rd());
+	PortOutput#(.ADDR(PC1)) p_pc1(.bus(bus),.data_to_bus(pcn[15:8]),.rd());
+endmodule
+
+`timescale 100ps/100ps
+module pc_block_tb;
+	reg clk, rst;
+
+	IBus bus0(clk, rst);
+	pc_block#(.PROGRAM("../../memory/oisc8.text")) pc0(bus0.port, bus0.iport);
+
+	initial forever#500ns clk = ~clk;
+	initial begin
+		clk = 0;
+		rst = 1;
+		#1100ns;
+		rst = 0;
+	end
+	
+endmodule

+ 32 - 4
tools/asm_compiler.py

@@ -448,6 +448,30 @@ class Compiler:
                     raise CompilingError(f"%include is not implemented yet")  # TODO: Complete
                     continue
 
+                elif line_args[0].lower() == '%ifdef':
+                    if len(line_args) != 1:
+                        raise CompilingError(f"Invalid %ifdef arguments!")
+                    raise CompilingError(f"%ifdef is not implemented yet")  # TODO: Complete
+                    continue
+
+                elif line_args[0].lower() == '%ifndef':
+                    if len(line_args) != 1:
+                        raise CompilingError(f"Invalid %ifndef arguments!")
+                    raise CompilingError(f"%ifndef is not implemented yet")  # TODO: Complete
+                    continue
+
+                elif line_args[0].lower() == '%else':
+                    if len(line_args) != 0:
+                        raise CompilingError(f"Invalid %else arguments!")
+                    raise CompilingError(f"%else is not implemented yet")  # TODO: Complete
+                    continue
+
+                elif line_args[0].lower() == '%endif':
+                    if len(line_args) != 0:
+                        raise CompilingError(f"Invalid %endif arguments!")
+                    raise CompilingError(f"%endif is not implemented yet")  # TODO: Complete
+                    continue
+
                 if csect is None:
                     raise CompilingError(f"No section defined!")
 
@@ -513,12 +537,13 @@ class Compiler:
         return '\n'.join(res)
 
 
-def convert_to_binary(data):
-    a = '\n'.join([format(i, '08b') for i in data])
+def convert_to_binary(data, bit_width=8):
+    bin_data = ''.join([format(i, '08b') for i in data])
+    a = '\n'.join(bin_data[i*bit_width:i*bit_width+bit_width] for i in range(0, len(data)//bit_width))
     return a.encode()
 
 
-def convert_to_mem(data, width=1, uhex=False):
+def convert_to_mem(data, width=1, uhex=False, reverse=False):
     x = b''
 
     if uhex:
@@ -528,7 +553,10 @@ def convert_to_mem(data, width=1, uhex=False):
                 x += format(data[-(i * 2) - 1], f'02x').upper().encode()
         else:
             for i in range(len(data)):
-                x += format(data[-i - 1], f'02x').upper().encode()
+                if reverse:
+                    x += format(data[i], f'02x').upper().encode()
+                else:
+                    x += format(data[-i - 1], f'02x').upper().encode()
         return x
 
     if width == 2:

+ 51 - 17
tools/oisc8asm.py

@@ -150,7 +150,7 @@ if __name__ == '__main__':
     parser.add_argument('file', help='Files to compile')
     parser.add_argument('-t', '--output_type', choices=['bin', 'mem', 'binary', 'mif', 'uhex'], default='mem',
                         help='Output type')
-    parser.add_argument('-S', '--slice', default=-1, type=int, help='Slice output for section')
+    parser.add_argument('-S', '--slice', default=0, type=int, help='Slice output for section')
     parser.add_argument('-o', '--output', help='Output directory')
     parser.add_argument('-f', '--force', action='store_true', help='Force override output file')
     parser.add_argument('-s', '--stdout', action='store_true', help='Print to stdout')
@@ -165,7 +165,7 @@ if __name__ == '__main__':
     if not path.exists(output_dir):
         mkdir(output_dir)
 
-    if args.output_type == 'mem':
+    if args.output_type == 'mem' or args.output_type == 'binary':
         ext = '.mem'
     elif args.output_type == 'bin':
         ext = '.bin'
@@ -177,12 +177,10 @@ if __name__ == '__main__':
         ext = '.out'
     bname = path.basename(args.file).rsplit('.', 1)[0]
 
-    sformat = f'01d'
     outputs = []
     if args.slice > 0:
-        sformat = f'0{int(math.log10(args.slice)) + 1}d'
         for i in range(0, args.slice):
-            outputs.append(path.join(output_dir, f'{bname}{args.section}_{format(i, sformat)}{ext}'))
+            outputs.append(path.join(output_dir, f'{bname}{args.section}_{i}{ext}'))
     else:
         outputs = [path.join(output_dir, bname + args.section + ext)]
     if not args.stdout and not args.force:
@@ -197,27 +195,58 @@ if __name__ == '__main__':
         if section in data:
             width, length, size, bdata = data[section]
             asize = len(bdata)
+
             if size > 0:
                 bdataf = bdata + (size - len(bdata)) * bytearray(b'\x00')
             else:
                 bdataf = bdata
 
+            if section == '.text':
+                if len(bdata) % 4 != 0:
+                    bdata += b'\x00\x00'
+                bitblocks = [
+                    format(int.from_bytes(bdataf[i * 4:i * 4 + 2], 'big'), '013b') +
+                    format(int.from_bytes(bdataf[i * 4 + 2:i * 4 + 4], 'big'), '013b')
+                    for i in range(0, len(bdataf) // 4)
+                ]
+                bitblocks += ['0'*26] * (size//3 - len(bitblocks))
+                # calculate parity bit
+                bitblocks = [b + str(b.count('1') % 2) for b in bitblocks]
+                # divide into 3 for each memory chip
+            else:
+                bits = [
+                    format(int.form_bytes(bdataf[i * width:i * width + width], 'big'), f'0{width*2}b')
+                    for i in range(0, len(bdataf) // width)
+                ]
+                bitblocks = [bdataf]
+                # bitstring = ''.join(bits)
+                # bitstring += len(bitstring) % 8 * 27 * '0'  # fill to the integer byte
+                # x = int(bitstring, 2).to_bytes(len(bitstring) // 8, 'big')
+
             for i, output in enumerate(outputs):
+                block_chunks = []
+                chunk_width = 9 if section == '.text' else 16
+                for block in bitblocks:
+                    for j in range(len(outputs)):
+                        block_chunks.append(block[chunk_width * j:chunk_width * (j+1)])
 
-                y = bdataf[i::len(outputs)]
+                y = block_chunks[i::len(outputs)]
                 if args.output_type == 'binary':
-                    x = compiler.convert_to_binary(y)
-                elif args.output_type == 'mem':
-                    x = compiler.convert_to_mem(y, width=width)
-                elif args.output_type == 'mif':
-                    x = compiler.convert_to_mif(y, width=width, depth=len(y)/width)
-                elif args.output_type == 'uhex':
-                    x = compiler.convert_to_mem(y, width=width, uhex=True)
+                    x = '\n'.join(y).encode()
                 else:
-                    x = bytes(y)
+                    # merge bits chunks info bytes
+                    y = int(''.join(y), 2).to_bytes(len(y)//8, 'big')
+                    if args.output_type == 'mem':
+                        x = compiler.convert_to_mem(y, width=1, uhex=True, reverse=True)
+                    elif args.output_type == 'mif':
+                        x = compiler.convert_to_mif(y, width=width, depth=len(y)/width)
+                    elif args.output_type == 'uhex':
+                        x = compiler.convert_to_mem(y, width=width, uhex=True)
+                    else:
+                        x = bytes(y)
 
                 op = 'Printing' if args.stdout else 'Saving'
-                print(f"{op} {args.output_type} {section} data '{output}' [Size: {len(y)}B Slice: {format(i + 1, sformat)}/{len(outputs)}]")
+                print(f"{op} {args.output_type} {section} data '{output}' [Size: {len(y)}B Slice: {i+1}/{len(outputs)}]")
                 if args.stdout:
                     if args.decompile:
                         print(asmc.decompile(bdata))
@@ -226,8 +255,13 @@ if __name__ == '__main__':
                 else:
                     with open(output, 'wb') as of:
                         of.write(x)
-
-            print(f"Total {section} size: {len(bdata) / len(bdataf) * 100:.1f}% [{len(bdata)}B/{len(bdataf)}B]")
+            if section == '.text':
+                insUsed = int(asize)//2
+                insTotal = size//2
+                print(f"Total {section} size: {insUsed / insTotal * 100:.1f}% "
+                      f"[ {insUsed} instr / {insTotal} instr ]")
+            else:
+                print(f"Total {section} size: {asize / len(bdataf) * 100:.1f}% [{int(asize)}B/{len(bdataf)}B]")
         else:
             print(f'No such section {section}!')
     else: