Commit e086df31 authored by Daniel Schultz's avatar Daniel Schultz
Browse files

WIP

parent ef27c6c7
-- Generator : SpinalHDL v0.10.13 git head : 14af3dec3a4b5d86a8d9ac3876db9e562cd32727
-- Date : 29/07/2017, 17:40:19
-- Generator : SpinalHDL v0.10.14 git head : 39a6b8a9e29a138ca415488dfdac0410155d25f1
-- Date : 25/08/2017, 22:10:31
-- Component : AISoC
library ieee;
......
source ../config.tcl
#enable source blocks
set top_module AISoC
set test_bench AISoC_tb
set top_module Core
set test_bench Core_tb
source sources.tcl
exec xvhdl -work work ../../../${test_bench}.vhd -log ./output/logs/${test_bench}_xvhdl.log
exec xvhdl -work work ../../../TBs/${test_bench}.vhd -log ./output/logs/${test_bench}_xvhdl.log
exec xelab -debug typical -L unisims_ver ${test_bench} -s ${top_module}_func -log ./output/logs/${test_bench}_xelab.log
exec xsim ${top_module}_func -gui -wdb simulate_xsim.wdb -view synth.wcfg -log ./output/logs/${top_module}_xsim.log
This diff is collapsed.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.pkg_scala2hdl.all;
use work.all;
use work.pkg_enum.all;
entity Core_tb is
end Core_tb;
architecture arch of Core_tb is
signal io_inst_addr : std_logic_vector(31 downto 0);
signal io_inst_trans : std_logic;
signal io_inst_ack : std_logic;
signal io_inst_data : std_logic_vector(31 downto 0);
signal io_dataAddr : std_logic_vector(31 downto 0);
signal io_dataTrans : std_logic;
signal io_dataLoad : std_logic;
signal io_dataDataO : std_logic_vector(31 downto 0);
signal io_dataAck : std_logic;
signal io_dataDataI : std_logic_vector(31 downto 0);
signal io_clk_cpu : std_logic;
signal resetCtrl_coreReset : std_logic := '1';
-- Procedure for clock generation
procedure clk_gen(signal clk : out std_logic; constant FREQ : real) is
constant PERIOD : time := 1 sec / FREQ; -- Full period
constant HIGH_TIME : time := PERIOD / 2; -- High time
constant LOW_TIME : time := PERIOD - HIGH_TIME; -- Low time; always >= HIGH_TIME
begin
-- Check the arguments
assert (HIGH_TIME /= 0 fs)
report "clk_plain: High time is zero; time resolution to large for frequency"
severity FAILURE;
-- Generate a clock cycle
loop
clk <= '1';
wait for HIGH_TIME;
clk <= '0';
wait for LOW_TIME;
end loop;
end procedure;
procedure clk_wait(constant FREQ : real; constant MULT : real) is
constant PERIOD : time := 1 sec / FREQ; -- Full period
begin
wait for PERIOD * MULT;
end procedure;
function to_std_logic_vector(a : string) return std_logic_vector is
variable ret : std_logic_vector(31 downto 0);
begin
for i in 0 to 31 loop
ret((i*4)+7 downto (i*4)) := std_logic_vector(to_unsigned(character'pos(a(i)), 4));
end loop;
return ret;
end function to_std_logic_vector;
constant CLK_CPU : real := 100.0e6;
type memory is array(0 to 512) of std_logic_vector(31 downto 0);
signal rom : memory := (
0 => x"00000013",
1 => x"00700513",
2 => x"32051073",
3 => x"32151073",
4 => x"c0002573",
5 => x"c0102573",
6 => x"c0202573",
7 => x"c0002573",
8 => x"c0102573",
9 => x"c0202573",
10 => x"b0002573",
11 => x"b0202573",
12 => x"f1102573",
13 => x"f1202573",
14 => x"f1302573",
15 => x"f1402573",
16 => x"30102573",
17 => x"08054513",
18 => x"30151073",
19 => x"30102573",
20 => x"30502573",
21 => x"00000517",
22 => x"0bc50513",
23 => x"30551073",
24 => x"30502573",
25 => x"10502573",
26 => x"00000517",
27 => x"0c450513",
28 => x"10551073",
29 => x"10502573",
30 => x"34102573",
31 => x"34202573",
32 => x"34302573",
33 => x"00000013",
34 => x"00000013",
35 => x"00000013",
36 => x"7ff00513",
37 => x"30251073",
38 => x"30351073",
39 => x"30202573",
40 => x"30302573",
41 => x"30253073",
42 => x"00000013",
43 => x"00000013",
44 => x"00000013",
45 => x"08400513",
46 => x"00451513",
47 => x"30051073",
48 => x"30200073",
49 => x"00300693",
50 => x"00300713",
51 => x"00300793",
52 => x"00300813",
53 => x"00300893",
54 => x"30079073",
55 => x"00400693",
56 => x"00400713",
57 => x"00400793",
58 => x"00400813",
59 => x"00400893",
60 => x"00000073",
61 => x"00500693",
62 => x"00500713",
63 => x"00500793",
64 => x"00500813",
65 => x"00500893",
66 => x"00000063",
67 => x"00000013",
68 => x"00300513",
69 => x"342025f3",
70 => x"34102673",
71 => x"00460613",
72 => x"30200073",
73 => x"00060067",
74 => x"00000013",
75 => x"00100513",
76 => x"342025f3",
77 => x"30200073",
others => x"00000013"
);
begin
clk_gen(io_clk_cpu, CLK_CPU);
resetCtrl_coreReset <= '0' after 50 ns;
io_inst_data <= rom(to_integer(unsigned(io_inst_addr(10 downto 2))));
io_inst_ack <= '1' after 5 ns when (io_inst_trans = '1') else
'0';
uut : entity work.Core
port map(
io_inst_addr => io_inst_addr,
io_inst_trans => io_inst_trans,
io_inst_ack => io_inst_ack,
io_inst_data => io_inst_data,
io_dataAddr => io_dataAddr,
io_dataTrans => io_dataTrans,
io_dataLoad => io_dataLoad,
io_dataDataO => io_dataDataO,
io_dataAck => io_dataAck,
io_dataDataI => io_dataDataI,
io_clk_cpu => io_clk_cpu,
resetCtrl_coreReset => resetCtrl_coreReset
);
end architecture;
......@@ -135,7 +135,7 @@ class WishboneMaster(
outPop.ready := ctrl.load
when (ctrl.load && ctrl.firstBurst) {
dat := outPop.payload(conf.addrWidth - 1, 0)
dat := outPop.payload(conf.dataWidth - 1, 0)
adr := outPop.payload(conf.dataWidth + conf.addrWidth - 1, conf.addrWidth).asUInt
we := outPop.payload(conf.dataWidth + conf.addrWidth)
} otherwise {
......
/*
* Copyright (C) 2017 Daniel Schultz <daniel.b.schultz@student.hs-rm.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.hsrm.aisoc.cpu.riscv
import spinal.core._
import spinal.lib._
import de.hsrm.aisoc.cpu.riscv.misc._
import de.hsrm.aisoc.bus.wishbone._
case class CacheWay(conf: RISCVCacheConfig) extends Component {
val io = new Bundle {
val addr = in Bits(conf.bus.addrWidth bits)
val lineData = in Bits(conf.bus.dataWidth * conf.lineSize bits)
val write = in Bool
val hit = out Bool
val data = out Bits(conf.bus.dataWidth bits)
}
def lineWidth() : Int = log2Up(conf.lineSize)
def indexWidth() : Int = log2Up(conf.tagCount)
def tagWidth() : Int = conf.bus.addrWidth - lineWidth() - indexWidth() - 2
def getTag(addr: Bits) : Bits = addr(tagWidth() + indexWidth() + lineWidth() + 1, indexWidth() + lineWidth() + 2)
def getIndex(addr: Bits) : Bits = addr(indexWidth() + lineWidth() + 1, lineWidth() + 2)
def getOffset(addr: Bits) : Bits = addr(lineWidth() + 1, 2)
val cache = new Area {
val way = Mem(Bits(conf.bus.dataWidth * conf.lineSize bits), wordCount = conf.tagCount)
val lineValue = Bits(conf.bus.dataWidth * conf.lineSize bits)
val tag = Mem(Bits(tagWidth() bits), wordCount = conf.tagCount)
val tagValue = Bits(tagWidth() bits)
val valid = RegInit(B(conf.tagCount bits, default -> False)) /* TODO */
val validFlag = Bool
lineValue := way.readAsync(
address = getIndex(io.addr).asUInt
)
way.write(
address = getIndex(io.addr).asUInt,
data = io.lineData,
enable = io.write
)
tagValue := tag.readAsync(
address = getIndex(io.addr).asUInt
)
tag.write(
address = getIndex(io.addr).asUInt,
data = getTag(io.addr),
enable = io.write
)
when (io.write) {
valid(getIndex(io.addr).asUInt) := True
}
validFlag := valid(getIndex(io.addr).asUInt)
}
val selector = new Area {
io.data := getOffset(io.addr).asUInt.muxList(
for(index <- 0 until conf.lineSize)
yield (index, cache.lineValue((index * conf.bus.dataWidth) + conf.bus.dataWidth - 1 downto index * conf.bus.dataWidth))
)
}
val comperator = new Area {
io.hit := (cache.tagValue === getTag(io.addr) && cache.validFlag)
}
}
......@@ -31,11 +31,7 @@ import de.hsrm.aisoc.cpu.riscv.misc.Opcodes._
class Core(conf: RISCVConfig) extends Component {
val io = new Bundle {
val instAddr = out Bits(conf.instConf.bus.addrWidth bits)
val instTrans = out Bool
val instSize = out Bits(conf.instConf.bus.addrWidth / 8 bits)
val instAck = in Bool
val instData = in Bits(conf.instConf.bus.dataWidth bits)
val inst = master(Instruction(conf.instConf))
val dataAddr = out Bits(conf.dataConf.bus.addrWidth bits)
val dataTrans = out Bool
......@@ -106,51 +102,79 @@ class Core(conf: RISCVConfig) extends Component {
/* TODO: refactor after caches included */
val ifStage = new Area {
val pc = RegInit(U(conf.defaultPC, conf.instConf.bus.addrWidth bits))
val trans = RegInit(False)
val start = RegInit(True)
val trans = RegInit(False)
val transLatch = RegInit(False)
val finished = !(transLatch ^ io.inst.ack)
val jump = Bool
val dstPC = UInt(conf.instConf.bus.addrWidth bits)
val lck2 = RegInit(False)
val lck2 = RegInit(False)
val instData = RegInit(B"x00000013")
val lck = RegInit(False)
val lckData = RegInit(B"x00000013")
/* TODO */
start := False
trans := (!interlock && !jump && !start && finished) /* TODO: Add stall */
when ((!interlock && !jump && !start && finished)) {
transLatch := True
} otherwise {
when (io.inst.ack) {
transLatch := False
}
}
lck2 := jump
when (!interlock) {
when (jump) {
pc := dstPC
} otherwise {
when (!lck2 && transLatch && finished) {
pc := pc + 4
}
}
}
/* TODO */
/*
when (!interlock) {
when (jump) {
pc := dstPC
lck2 := True
} otherwise {
when (start || io.instAck) {
when (start || io.inst.ack) {
lck2 := False
when (!lck2) {
pc := pc + 4
}
}
}
when (start || io.instAck) {
when (start || io.inst.ack) {
trans := True
start := False
} otherwise {
trans := False
}
} otherwise {
when (io.instAck) {
when (io.inst.ack) {
start := True
}
trans := False
}
*/
when (!interlock && lck) {
lck := False
instData := lckData
} otherwise {
when (io.instAck) {
when (io.inst.ack) {
when (interlock) {
lck := True
lckData := io.instData
lckData := io.inst.data
} otherwise {
instData := io.instData
instData := io.inst.data
}
} otherwise {
instData := B"x00000013"
......@@ -158,9 +182,9 @@ class Core(conf: RISCVConfig) extends Component {
}
/* --- */
}
io.instAddr := ifStage.pc.asBits
io.instTrans := ifStage.trans
io.instSize := B(conf.instConf.bus.addrWidth / 8 bits, default -> True)
io.inst.addr := ifStage.pc.asBits
io.inst.trans := ifStage.trans
io.inst.size := B(conf.instConf.bus.addrWidth / 8 bits, default -> True)
val idStage = new Area {
registers.rs1Adr := ifStage.instData(rs1Range).asUInt
......@@ -172,146 +196,144 @@ class Core(conf: RISCVConfig) extends Component {
val rs2Adr = RegInit(U(0, regAdrWidth bits))
val immVal = RegInit(S(0, conf.xlen bits))
val pc = RegInit(U(conf.defaultPC, conf.instConf.bus.addrWidth bits))
rdAdr := ifStage.instData(rdRange).asUInt
rs1Adr := ifStage.instData(rs1Range).asUInt
rs1Val := registers.rs1Val
rs2Adr := ifStage.instData(rs2Range).asUInt
rs2Val := registers.rs2Val
when (io.instAck) {
pc := ifStage.pc
}
val instHolder = Reg(InstHolder())
instHolder.op1 := OP1.REG
instHolder.op2 := OP2.REG
instHolder.alu := ALU.NONE
instHolder.shft := SHFT.NONE
instHolder.inv := False
instHolder.cmp := CMP.NONE
instHolder.mem := MEM.NONE
instHolder.size := MEMSIZE.B
instHolder.wb := True
instHolder.jump := False
when (ifStage.instData(opcodeRange) === BASE) {
when (ifStage.instData(opcodeRange) === BASE_MEM) {
instHolder.alu := ALU.ADD
instHolder.op2 := OP2.IMM
instHolder.size.assignFromBits(ifStage.instData(funct3Range)(1, 0))
when (ifStage.instData(opcodeRange) === MEM_LOAD) {
immVal := ifStage.instData(immIType).asSInt.resize(conf.xlen)
when (ifStage.instData(funct3Range).msb) {
instHolder.mem := MEM.LOADU
} otherwise {
instHolder.mem := MEM.LOAD
}
}
when (ifStage.instData(opcodeRange) === MEM_STORE) {
immVal := (ifStage.instData(immSType) ## ifStage.instData(rdRange)).asSInt.resize(conf.xlen)
instHolder.mem := MEM.STORE
instHolder.wb := False
}
when (!interlock) {
rdAdr := ifStage.instData(rdRange).asUInt
rs1Adr := ifStage.instData(rs1Range).asUInt
rs1Val := registers.rs1Val
rs2Adr := ifStage.instData(rs2Range).asUInt
rs2Val := registers.rs2Val
when (io.inst.ack) {
pc := ifStage.pc
}
when (ifStage.instData(opcodeRange) === BASE_ALU) {
when (ifStage.instData(opcodeRange) === ALU_IMM) {
instHolder.alu.assignFromBits(ifStage.instData(funct3Range))
instHolder.shft.assignFromBits(ifStage.instData(funct3Range))
instHolder.op1 := OP1.REG
instHolder.op2 := OP2.REG
instHolder.alu := ALU.NONE
instHolder.shft := SHFT.NONE
instHolder.inv := False
instHolder.cmp := CMP.NONE
instHolder.mem := MEM.NONE
instHolder.size := MEMSIZE.B
instHolder.wb := True
instHolder.jump := False
when (ifStage.instData(opcodeRange) === BASE) {
when (ifStage.instData(opcodeRange) === BASE_MEM) {
instHolder.alu := ALU.ADD
instHolder.op2 := OP2.IMM
when (ifStage.instData(funct3Range) === "001" ||
ifStage.instData(funct3Range) === "101") {
immVal := ifStage.instData(rs2Range).asSInt.resize(conf.xlen)
instHolder.inv := ifStage.instData(30)
} otherwise {
instHolder.size.assignFromBits(ifStage.instData(funct3Range)(1, 0))
when (ifStage.instData(opcodeRange) === MEM_LOAD) {
immVal := ifStage.instData(immIType).asSInt.resize(conf.xlen)
when (ifStage.instData(funct3Range).msb) {
instHolder.mem := MEM.LOADU
} otherwise {
instHolder.mem := MEM.LOAD
}
}
when (ifStage.instData(opcodeRange) === MEM_STORE) {
immVal := (ifStage.instData(immSType) ## ifStage.instData(rdRange)).asSInt.resize(conf.xlen)
instHolder.mem := MEM.STORE
instHolder.wb := False
}
}
when (ifStage.instData(opcodeRange) === ALU_AUIPC) {
instHolder.alu := ALU.ADD
instHolder.op1 := OP1.PC
instHolder.op2 := OP2.IMM
immVal := (ifStage.instData(immUType) ## B"x000").asSInt.resize(conf.xlen)
}
when (ifStage.instData(opcodeRange) === ALU_LUI) {
instHolder.alu := ALU.ADD
instHolder.op1 := OP1.ZERO
instHolder.op2 := OP2.IMM
immVal := (ifStage.instData(immUType) ## B"x000").asSInt.resize(conf.xlen)
}
when (ifStage.instData(opcodeRange) === ALU_REG) {
instHolder.alu.assignFromBits(ifStage.instData(funct3Range))
instHolder.shft.assignFromBits(ifStage.instData(funct3Range))
instHolder.inv := ifStage.instData(30)
}
}
when (ifStage.instData(opcodeRange) === BASE_BRANCH) {
instHolder.alu := ALU.ADD
instHolder.op2 := OP2.IMM
instHolder.jump := True
when (ifStage.instData(opcodeRange) === BRANCH_B) {
instHolder.op1 := OP1.PC
instHolder.wb := False
instHolder.cmp.assignFromBits(ifStage.instData(funct3Range))
val imm = ifStage.instData(immSType) ## ifStage.instData(rdRange)
immVal := (imm(11) ## imm(0) ## imm(10 downto 5) ## imm(4 downto 1) ## "0").asSInt.resize(conf.xlen)
when (ifStage.instData(opcodeRange) === BASE_ALU) {
when (ifStage.instData(opcodeRange) === ALU_IMM) {
instHolder.alu.assignFromBits(ifStage.instData(funct3Range))
instHolder.shft.assignFromBits(ifStage.instData(funct3Range))
instHolder.op2 := OP2.IMM
when (ifStage.instData(funct3Range) === "001" ||
ifStage.instData(funct3Range) === "101") {
immVal := ifStage.instData(rs2Range).asSInt.resize(conf.xlen)
instHolder.inv := ifStage.instData(30)
} otherwise {
immVal := ifStage.instData(immIType).asSInt.resize(conf.xlen)
}
}
when (ifStage.instData(opcodeRange) === ALU_AUIPC) {
instHolder.alu := ALU.ADD
instHolder.op1 := OP1.PC
instHolder.op2 := OP2.IMM
immVal := (ifStage.instData(immUType) ## B"x000").asSInt.resize(conf.xlen)
}
when (ifStage.instData(opcodeRange) === ALU_LUI) {
instHolder.alu := ALU.ADD
instHolder.op1 := OP1.ZERO
instHolder.op2 := OP2.IMM
immVal := (ifStage.instData(immUType) ## B"x000").asSInt.resize(conf.xlen)
}
when (ifStage.instData(opcodeRange) === ALU_REG) {
instHolder.alu.assignFromBits(ifStage.instData(funct3Range))
instHolder.shft.assignFromBits(ifStage.instData(funct3Range))
instHolder.inv := ifStage.instData(30)
}
}
when (ifStage.instData(opcodeRange) === BRANCH_JAL) {
instHolder.op1 := OP1.PC
instHolder.cmp := CMP.JUMP
val imm = ifStage.instData(immUType)
/* TODO Check */
immVal := (imm(19) ## imm(7 downto 0) ## imm(8) ## imm(18 downto 9) ## "0").asSInt.resize(conf.xlen)
when (ifStage.instData(opcodeRange) === BASE_BRANCH) {
instHolder.alu := ALU.ADD
instHolder.op2 := OP2.IMM
instHolder.jump := True